home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 5
/
Aminet 5 - March 1995.iso
/
Aminet
/
util
/
arc
/
VEC_3_231.lha
/
vec3231
/
source
/
vdc.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-12-08
|
17KB
|
1,020 lines
/*
* VDC.C (VEC)
*
* Copyright (c) 1991, 1992, 1993 Ville Saari
* All rights reserved
*
* Created: 23-Dec-91
* Updated: 05-Dec-93
*/
#include "vec.h"
#define MC 181
#define UC 252
#define EC 253
#define HW 254
#define VW 255
#define hws(c) (decodetab[c]==HW)
#define vws(c) (decodetab[c]==VW)
#define ws(c) (decodetab[c]>=HW)
const static unsigned char decodetab[256]=
{
/* unused characters, white space characters and end character: */
UC, UC, UC, UC, UC, UC, UC, UC, UC, HW, VW, VW, UC, VW, UC, UC,
UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC,
HW, EC, UC, UC,
/* bytes used by all methods: */
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
/* additional bytes for >=6.5 bit methods: */
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
/* unused characters */
UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC,
UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC,
/* additional bytes for >=7 bit methods: */
91, 92, 93, 94, 95, 96, 97, 98, 99, 100,
101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
121, 122, 123, 124, 125, 126, 127,
/* additional bytes for 7.5 bit method: */
128, 129, 130, 131, 132, 133, 134, 135, 136, 137,
138, 139, 140, 141, 142, 143, 144, 145, 146, 147,
148, 149, 150, 151, 152, 153, 154, 155, 156, 157,
158, 159, 160, 161, 162, 163, 164, 165, 166, 167,
168, 169, 170, 171, 172, 173, 174, 175, 176, 177,
178, 179, 180, 181,
/* unused characters */
UC, UC, UC, UC
};
static unsigned char uudecodetab[256];
static struct namedata
{
struct namedata *next;
int count;
char name[1];
} *ndbase=0;
static unsigned char *start;
static unsigned char linedelim;
static void sevenandhalfbitdecoder(const unsigned char *i, unsigned char *o)
{
unsigned int z;
unsigned char *p=o+8;
z=*i++; z+=182**i++; *o++=z; *p++=z>>8;
z=*i++; z+=182**i++; *o++=z; *p++=z>>8;
z=*i++; z+=182**i++; *o++=z; *p++=z>>8;
z=*i++; z+=182**i++; *o++=z; *p++=z>>8;
z=*i++; z+=182**i++; *o++=z; *p++=z>>8;
z=*i++; z+=182**i++; *o++=z; *p++=z>>8;
z=*i++; z+=182**i++; *o++=z; *p =z>>8;
z=*i++; z+=182**i ; *o++=z;
*o++|=(z>>=1)&0x80;
*o++|=(z>>=1)&0x80;
*o++|=(z>>=1)&0x80;
*o++|=(z>>=1)&0x80;
*o++|=(z>>=1)&0x80;
*o++|=(z>>=1)&0x80;
*o |=(z>>=1)&0x80;
}
static void sevenbitdecoder(const unsigned char *i, unsigned char *o)
{
unsigned int z;
z=i[7];
*o++=*i++|(z<<7);
*o++=*i++|(z<<6)&0x80;
*o++=*i++|(z<<5)&0x80;
*o++=*i++|(z<<4)&0x80;
*o++=*i++|(z<<3)&0x80;
*o++=*i++|(z<<2)&0x80;
*o =*i |(z<<1)&0x80;
}
static void sixandhalfbitdecoder(const unsigned char *i, unsigned char *o)
{
unsigned int z;
unsigned char *p=o+8;
z=*i++; z+=91**i++; *o++=z; *p++=z>>8;
z=*i++; z+=91**i++; *o++=z; *p++=z>>8;
z=*i++; z+=91**i++; *o++=z; *p++=z>>8;
z=*i++; z+=91**i++; *o++=z; *p++=z>>8;
z=*i++; z+=91**i++; *o++=z; *p =z>>8;
z=*i++; z+=91**i++; *o++=z;
p[-4]|=(z>>3)&0xe0;
p[-1]|=(z>>6)&0x60;
z=*i++; z+=91**i++; *o++=z;
p[-3]|=(z>>3)&0xe0;
p[ 0]|=(z>>6)&0x60;
z=*i++; z+=91**i; *o=z;
p[-2]|=(z>>3)&0xe0;
p[-1]|=(z>>4)&0x80;
p[ 0]|=(z>>5)&0x80;
}
static void sixbitdecoder(const unsigned char *i, unsigned char *o)
{
unsigned int z;
z=i[6];
*o++=*i++|(z<<6)&0xc0;
*o++=*i++|(z<<4)&0xc0;
*o++=*i++|(z<<2)&0xc0;
z=i[4];
*o++=*i++|(z<<6)&0xc0;
*o++=*i++|(z<<4)&0xc0;
*o =*i |(z<<2)&0xc0;
}
static int gethexval(unsigned char val)
{
return val-(val<25?12:val<48?19:51);
}
static void hexdecoder(const unsigned char *i, unsigned char *o)
{
*o=gethexval(i[0])<<4|gethexval(i[1]);
}
static int fecdecoder(void)
{
int c;
do {
if(inptr>=inbufend && !fillbuffer(1)) return -7;
c=*inptr++;
}
while(vws(c));
if(c>=248) return c==248?-7:-c+248;
return c-(c>159?65:33);
}
static int btoadecoder(unsigned char *buf)
{
int c;
unsigned long z;
do {
if(inptr>=inbufend && !fillbuffer(1)) return 0;
c=*inptr++;
}
while(vws(c));
if(c=='z')
{
buf[0]=buf[1]=buf[2]=buf[3]=0;
return 1;
}
if(c=='x') return 0;
z=((unsigned long)(c-'!'))*(85*85*85*85);
do {
if(inptr>=inbufend && !fillbuffer(1)) return 0;
c=*inptr++;
}
while(vws(c));
z+=((unsigned long)(c-'!'))*(85*85*85);
do {
if(inptr>=inbufend && !fillbuffer(1)) return 0;
c=*inptr++;
}
while(vws(c));
z+=((unsigned long)(c-'!'))*(85*85);
do {
if(inptr>=inbufend && !fillbuffer(1)) return 0;
c=*inptr++;
}
while(vws(c));
z+=((unsigned long)(c-'!'))*85;
do {
if(inptr>=inbufend && !fillbuffer(1)) return 0;
c=*inptr++;
}
while(vws(c));
z+=(unsigned long)(c-'!');
*buf++=(unsigned char)(z>>24);
*buf++=(unsigned char)(z>>16);
*buf++=(unsigned char)(z>>8);
*buf =(unsigned char)z;
return 1;
}
static void getname(const char *from, char *to, const char *s)
{
struct namedata *nd;
strncpy(to, from, 256);
for(nd=ndbase; nd; nd=nd->next)
if(!strcmp(nd->name, from))
{
nd->count++;
modifyname(to, nd->count);
if(!silent)
{
printerr(from);
printerr(" -> ");
printerr(to);
printerr(s);
}
return;
}
if(nd=(struct namedata *)malloc(strlen(to)+sizeof *nd))
{
strcpy(nd->name, to);
nd->count=0;
nd->next=ndbase;
ndbase=nd;
}
if(!silent)
{
printerr(to);
printerr(s);
}
}
static int getline(unsigned char *buf, int size)
{
unsigned char c=0, *e=buf+size;
do {
if(inptr>=inbufend && !fillbuffer(1)) goto end;
c=*inptr++;
}
while(vws(c));
do {
*buf++=c;
if(inptr>=inbufend && !fillbuffer(1)) break;
c=*inptr++;
}
while(!vws(c) && buf<e);
end:
linedelim=c;
*buf=0;
return size-(e-buf);
}
static int myfile;
static unsigned char namebuf[256];
static void startoutput(const unsigned char *filename, const unsigned char *method)
{
if(lines==1)
{
#ifdef FINNISH
writefile(stdoutfile, "### Koodattu tiedosto poistettu: ", 33);
#else
writefile(stdoutfile, "### Encoded file removed: ", 26);
#endif
writefile(stdoutfile, filename, strlen(filename));
writefile(stdoutfile, method, strlen(method));
}
if(outfileflag || pipe)
{
if(!silent)
{
printerr(filename);
printerr(method);
}
myfile=0;
}
else
{
getname(filename, namebuf, method);
if(failedopen(outfile=openwrite(namebuf, 1)))
{
#ifdef FINNISH
printerrh("Tiedosto `");
printerr(namebuf);
printerr("' ei aukea.\n");
#else
printerrh("Can't open output file `");
printerr(namebuf);
printerr("'.\n");
#endif
errcleanup(0);
}
outfileflag=myfile=1;
}
}
static void endoutput(const unsigned char *flags)
{
if(!myfile) return;
flushoutput();
closefile(outfile);
outfileflag=myfile=0;
if(flags && !nomode) setfilemode(namebuf, flags);
}
static unsigned long illegal;
static int getvecblock(char *p, int size)
{
unsigned int c, r;
unsigned char *b;
do {
b=get(r=size);
if(trueread<size)
{
if(trueread && *b=='!') b++;
inptr=b;
return 0;
}
while(r--)
{
if((c=decodetab[*b++])>MC)
{
if(c==EC)
{
inptr=b;
return 0;
}
if(c==UC) illegal++;
}
else
{
*p++=c;
size--;
}
}
}
while(size);
return 1;
}
static unsigned short updatecrc(unsigned short crc, const unsigned char *p, unsigned long size)
{
while(size--) crc=(crc>>8)^crc16tab[(unsigned char)(crc^*p++)];
return crc;
}
static int decodevec(unsigned char *linebuf)
{
unsigned char flags[6], inblockbuf[16], *p, *startptr=outptr;
void (*decoder)(const unsigned char *, unsigned char *);
int inblock, outblock, makecrc, crc, t, ok=1;
*linebuf=0;
crc=0;
illegal=0;
if(strlen(linebuf+1)<14)
{
#ifdef FINNISH
printerr("Virheellinen vec headeri!\n");
#else
printerr("Corrupted vec header!\n");
#endif
return 0;
}
for(p=linebuf+7; p<linebuf+15; p++) *p=decodetab[*p];
sixbitdecoder(linebuf+7, flags);
if(linebuf[15])
startoutput(linebuf+15, "\n");
else
startoutput("noname", "\n");
makecrc=((flags[0]&1) && !quick);
switch(linebuf[6])
{
case '3':
decoder=sevenandhalfbitdecoder;
inblock=16;
outblock=15;
break;
case '2':
decoder=sevenbitdecoder;
inblock=8;
outblock=7;
break;
case '1':
decoder=sixandhalfbitdecoder;
inblock=16;
outblock=13;
break;
case '0':
decoder=sixbitdecoder;
inblock=8;
outblock=6;
break;
case 'x':
decoder=hexdecoder;
inblock=2;
outblock=1;
break;
case 'a':
inblock=0;
outblock=0;
break;
case 'i':
inblock=0;
outblock=1;
break;
default:
{
#ifdef FINNISH
static char herja[]=" Tuntematon koodausmenetelm" a_ " ` '!\n";
herja[32]=linebuf[6];
printerr(herja);
#else
static char nag[]=" Unknown coding method ` '!\n";
nag[26]=linebuf[6];
printerr(nag);
#endif
endoutput(0);
return 0;
}
}
if(inblock)
{
while(getvecblock(inblockbuf, inblock))
{
if(outptr>=outbufend)
{
if(makecrc) crc=updatecrc(crc, startptr, outptr-startptr);
flushoutput();
startptr=outptr;
}
decoder(inblockbuf, outptr);
outptr+=outblock;
}
}
else
{
unsigned char c;
for(;;)
{
if(inptr>=inbufend && !fillbuffer(1)) break;
c=*inptr++;
if(c==94 || c==92 && !outblock)
{
unsigned char c2=c;
if(inptr>=inbufend && !fillbuffer(1)) break;
c=*inptr++;
if(c2==94)
if(vws(c))
continue;
else if((c&0xe0)==0x40)
c-=64;
else if((c&0xe0)==0x60)
c+=32;
else if(c==33)
break;
else if(c==63)
c=127;
else if(c==62)
c=159;
else if(c==61)
c=94;
else if(c==60 && !outblock)
c=92;
else if(c==59 && !outblock)
c=255;
else
{
if(makecrc) crc=(crc>>8)^crc16tab[(unsigned char)(crc^94)];
put1(94);
}
else
c+=128;
}
else if(vws(c) && c!=10)
continue;
if(makecrc) crc=(crc>>8)^crc16tab[(unsigned char)(crc^c)];
put1(c);
}
}
if(!getvecblock(p=inblockbuf, (inblock?1:0)+(makecrc?4:0)))
{
#ifdef FINNISH
printerr(" Tiedosto loppui kesken!\n");
#else
printerr(" Premature EOF!\n");
#endif
}
else
{
if(inblock)
{
if((t=gethexval(*p++))>outblock || t<0)
{
#ifdef FINNISH
printerr(" Virheellinen lopetin!\n");
#else
printerr(" Incorrect terminator!\n");
#endif
}
else
outptr-=t;
crc=updatecrc(crc, startptr, outptr-startptr);
}
if(makecrc)
{
if(crc!=(gethexval(p[0])<<12|gethexval(p[1])<<8|
gethexval(p[2])<<4|gethexval(p[3])))
{
#ifdef FINNISH
printerr(" CRC virhe!\n");
#else
printerr(" CRC mismatch!\n");
#endif
ok=0;
}
}
}
if(illegal)
{
#ifdef FINNISH
printerr(" Koodi sis" a_ "lsi ");
if(illegal==1)
printerr("laittoman merkin!\n");
else
{
printerr(ltoa(illegal));
printerr(" laitonta merkki" a_ "!\n");
}
#else
printerr(" Code contained ");
if(illegal==1)
printerr("illegal character!\n");
else
{
printerr(ltoa(illegal));
printerr(" illegal characters!\n");
}
#endif
}
endoutput(flags);
return ok;
}
static void resetuudecodetab(void)
{
int f;
for(f=0; f<256; f++)
uudecodetab[f]=f-' '&0x3f;
}
static int readuudecodetab(unsigned char *linebuf)
{
int f, c;
*linebuf=0;
for(f=0; f<64; f++)
{
do c=get1(); while(c>=0 && vws(c));
uudecodetab[c]=f;
}
if((c=get1())<0 || !vws(c))
{
#ifdef FINNISH
printerr("Virheellinen uuencodetaulukko!\n");
#else
printerr("Incorrect uuencode table!\n");
#endif
resetuudecodetab();
return 0;
}
return 1;
}
static int decodeuu(unsigned char *linebuf)
{
int ercount=0, sum, n, cont=1;
unsigned long size=0;
long mode=0;
unsigned char c, *p, flagbuf[6];
*linebuf=0;
for(p=linebuf+6; hws(*p); p++);
while(*p>='0' && *p<='7') mode=(mode<<3)|*p++-'0';
while(hws(*p)) p++;
#ifdef FINNISH
startoutput(p, " (uuenkoodattu)\n");
#else
startoutput(p, " (uuencoded)\n");
#endif
while(cont)
{
do {
if(inptr>=inbufend && !fillbuffer(1))
{
#ifdef FINNISH
printerr(" Tiedosto loppui kesken!\n");
#else
printerr(" Premature EOF!\n");
#endif
endoutput(0);
return 1;
}
c=*inptr++;
}
while(vws(c));
sum=0;
size+=n=uudecodetab[c];
p=get((n+2)/3*4+1);
if(outptr>outbufend-63) flushoutput();
if(!n) cont=0;
while(n>0)
{
unsigned char a=uudecodetab[*p++], b;
sum+=*outptr++=a<<2|(b=uudecodetab[*p++])>>4;
sum+=*outptr++=b<<4|(a=uudecodetab[*p++])>>2;
sum+=*outptr++=a<<6| uudecodetab[*p++];
n-=3;
}
outptr+=n;
if(!quick && !(vws(*p)) && (sum&0x3f)!=uudecodetab[*p]) ercount++;
}
flagbuf[2]=2;
flagbuf[4]=(mode>>8)&0x01;
flagbuf[5]=mode;
endoutput(flagbuf);
if(ercount)
{
printerr(" ");
#ifdef FINNISH
if(ercount==1)
printerr("tarkistussummavirhe!\n");
else
{
printerr(ltoa(ercount));
printerr(" tarkistussummavirhett" a_ "!\n");
}
#else
if(ercount==1)
printerr("checksum error!\n");
else
{
printerr(ltoa(ercount));
printerr(" checksum errors!\n");
}
#endif
}
getline(linebuf, 512);
if(strcmp(linebuf, "end"))
{
#ifdef FINNISH
printerr(" `end'-rivi puuttuu!\n");
#else
printerr(" No `end'-line!\n");
#endif
ercount++;
}
else
getline(linebuf, 512);
if(!strncmp(linebuf, "size ", 5))
{
if(atol(linebuf+5)!=size)
{
#ifdef FINNISH
printerr(" Kokovirhe!\n");
#else
printerr(" Size mismatch!\n");
#endif
ercount++;
}
*linebuf=0;
}
if(resetuu) resetuudecodetab();
return ercount==0;
}
static int decodefec(unsigned char *linebuf)
{
int start=1, f;
unsigned char outblock[7], *p;
*linebuf=0;
#ifdef FINNISH
startoutput(linebuf+3, " (fipenkoodattu)\n");
#else
startoutput(linebuf+3, " (fipencoded)\n");
#endif
for(;;)
{
if((f=fecdecoder())<0) break;
if(start)
start=0;
else
put(outblock, 7);
p=outblock;
*p++=(f<<1)|(f=fecdecoder())>>6;
*p++=(f<<2)|(f=fecdecoder())>>5;
*p++=(f<<3)|(f=fecdecoder())>>4;
*p++=(f<<4)|(f=fecdecoder())>>3;
*p++=(f<<5)|(f=fecdecoder())>>2;
*p++=(f<<6)|(f=fecdecoder())>>1;
*p =(f<<7)|fecdecoder();
}
put(outblock, -f);
endoutput(0);
return 1;
}
static int decodebtoa(unsigned char *linebuf)
{
unsigned char outblock[2][4];
int start=1, dataout=0, i=0, datasize, ok=1;
*linebuf=0;
#ifdef FINNISH
startoutput("noname", " (btoa:ttu)\n");
#else
startoutput("noname", " (btoa'd)\n");
#endif
while(btoadecoder(outblock[i]))
{
i=!i;
if(start)
start=0;
else
{
put(outblock[i], 4);
dataout+=4;
}
}
getline(linebuf, 512);
if(strncmp(linebuf, "btoa End N ", 11))
{
#ifdef FINNISH
printerr(" `btoa End'-rivi puuttuu!\n");
#else
printerr(" No `btoa End'-line!\n");
#endif
}
else
{
*linebuf=0;
if((datasize=atol(linebuf+11))<dataout || datasize>dataout+4)
{
#ifdef FINNISH
printerr(" Kokovirhe!\n");
#else
printerr(" Size mismatch!\n");
#endif
ok=0;
}
else
put(outblock[!i], datasize-dataout);
}
endoutput(0);
return ok;
}
static int fillbufferandprint(int yes)
{
int rc;
if(lines && yes) writefile(stdoutfile, start, inptr-start);
rc=fillbuffer(1);
start=inptr;
return rc;
}
int vdc(void)
{
int ok=1, lineswait=0;
unsigned char c, linebuf[512], *end;
resetuudecodetab();
start=inptr;
for(;;)
{
/* check the first character of the line */
do {
if(inptr>=inbufend && !fillbufferandprint(!lineswait)) return ok;
c=*inptr++;
}
while(vws(c));
if(lineswait)
{
lineswait=0;
start=inptr-1;
}
if(c!='F' && c!='b' && c!='y' && c!='x' && c!='t')
{
/* find vertical white space character */
nextline:
do {
if(inptr>=inbufend && !fillbufferandprint(1)) return ok;
c=*inptr++;
}
while(!vws(c));
continue;
}
inptr--;
/* ensure 512 characters or rest of file in the buffer */
if(inptr>inbuf+bufsize-512)
{
long s;
if(lines) writefile(stdoutfile, start, inptr-start);
memcpy(inbuf, inptr, s=inbufend-inptr);
inbufend=inbuf+s;
fillbuffer(0);
inptr=start=inbuf;
}
end=inptr++;
/* get the line */
{
char *p=linebuf;
int maxl=inbufend-inptr;
if(maxl>511) maxl=511;
do *p++=c, c=*inptr++; while(--maxl && !vws(c));
*p=0;
}
/* and test the magics */
for(;;)
{
int (*func)(unsigned char *);
if(!strncmp(linebuf, "yobufi", 6))
func=decodevec;
else if(!strncmp(linebuf, "begin ", 6))
func=decodeuu;
else if(!strncmp(linebuf, "table", 6))
func=readuudecodetab;
else if(!strncmp(linebuf, "FEC", 3))
func=decodefec;
else if(!strncmp(linebuf, "xbtoa Begin", 11))
func=decodebtoa;
else
{
if(end) break;
if(!*linebuf)
lineswait=1;
else if(lines)
{
writefile(stdoutfile, linebuf, strlen(linebuf));
writefile(stdoutfile, &linedelim, 1);
}
start=inptr;
break;
}
if(lines && end>start)
writefile(stdoutfile, start, end-start);
end=0;
ok&=func(linebuf);
}
}
}